#include "Game.h"
#include "Timer.h"
#include "GameState.h"
#include "ScreenManager.h"
#include "StringUtilities.h"
#include "DX11ErrorReport.h"
#include "EventPoller.h"

#include <assert.h>


Game::Game()
{
	m_state = 0;
}

Game::~Game()
{
	SDL_Quit();
}

void Game::RunGame()
{
	TheTimer::Instance()->UpdateTime();

	Update();
	Draw();
}

void Game::Draw()
{
	m_state->Draw();
}

void Game::Update()
{
	// add event poller
	m_state->Update();
}

void Game::SetGameState(GameState* gs)
{
	if (m_state != gs)
	{
		if (m_state)
		{
			m_state->OnDeactivated();
		}
		m_state = gs;
		m_state->OnActivated();
	}
}

void Game::AddGameObject(int id, GameObject* g)
{
	if (m_gameObjects.find(id) != m_gameObjects.end())
	{
		std::string test = g->GetTypeName();
		std::wstring errorMsg(test.begin(), test.end());
		errorMsg = L"Game object id already exists! " + StringToWString(g->GetTypeName());

		DX11ErrorMsg(errorMsg.c_str(), L"Game object load failed", MB_YESNO);
	}
	m_gameObjects[id] = g;
}

void Game::UpdateGameObjects()
{
	for (GameObjectMap::iterator it = m_gameObjects.begin(); it != m_gameObjects.end(); ++it)
	{
		it->second->Update();
	}

	UpdateCollisions();
}

void Game::DrawGameObjects()
{
	for (GameObjectMap::iterator it = m_gameObjects.begin(); it != m_gameObjects.end(); ++it)
	{
		it->second->Draw();
	}
}

void Game::DrawMiniMapGameObjects()
{
	for (GameObjectMap::iterator it = m_gameObjects.begin(); it != m_gameObjects.end(); ++it)
	{
		it->second->DrawMiniMapElements();
	}
}

void Game::DrawMiniMapColourPickObjects()
{
	for (GameObjectMap::iterator it = m_gameObjects.begin(); it != m_gameObjects.end(); ++it)
	{
		it->second->DrawMiniMapColourPick();
	}
}

void Game::DrawColourPickObjects()
{
	for (GameObjectMap::iterator it = m_gameObjects.begin(); it != m_gameObjects.end(); ++it)
	{
		it->second->DrawColourPick();
	}
}

void Game::UpdateCollisions()
{
	assert(m_pCollisionSystem);

	m_pCollisionSystem->Update(&m_gameObjects);
}

void Game::HandleCollisions(GameObject* A, GameObject* B)
{
	std::string s1 = A->GetTypeName();
	std::string s2 = B->GetTypeName();

	KeyType k(s1, s2);
	CollisionMap::iterator it = m_collisionMap.find(k);

	if (it == m_collisionMap.end())
	{
		std::swap(s1, s2);
		k = KeyType(s1, s2);
		it = m_collisionMap.find(k);
		if (it != m_collisionMap.end())
		{
			CollisionHandler ch = it->second;
			ch(B, A);
		}
	}
	else
	{
		CollisionHandler ch = it->second;
		ch(A, B);
	}
}

bool Game::AddCollisionHandler(const std::string& s1, const std::string& s2, CollisionHandler ch)
{
	KeyType k(s1, s2);
	m_collisionMap[k] = ch;

	return true;
}

void Game::SetCollisionSystem(CollisionSystem* cs)
{
	m_pCollisionSystem = cs;
}

void Game::ClearGameObjects()
{
	for (std::map<int, GameObject*>::iterator it = m_gameObjects.begin(); it != m_gameObjects.end(); ++it)
	{
		delete it->second;
	}
	m_gameObjects.clear();
}